package Socket;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

/**聊天室的客户端
 * V3版的客户端start方法中的主要逻辑是先等待用户在控制台上输入一行字符串，然后将其发送给
 * 服务端后再读取来自服务端发送过来的消息
 * 但是由于V4服务器已经改成了可以将其它客户端的消息也转发给所有客户端的操作，这会导致有源源
 * 不断的新消息发送给客户端，然后如果客户端必须先等待用户输入一行再接受一行来自服务端消息的
 * 话，会导致接收消息不畅问题
 *
 * 为了解决这个问题：
 * 我们应当将发送消息和接收消息的操作分别在不同的线程上运行，才能做到互不干涉
 *
 * 实现：
 * 我们将发送消息还定义在start方法中由客户端的主线程执行即可，将读取消息单独定义到一个线
 * 程上执行
 * 1.定义内部类serverHandler，这是一个线程任务，主要工作就是读取来自服务端发送的消息并输
 * 出到客户端的控制台上
 *  2:在start方法一开始就启动一个线程来执行ServerHandler这个任务,不断接收来自服务端的
 *  消息.
 *

 */
public class Clier4 {
    private Socket socket;

    public Clier4() {
        try {
            System.out.println("正在连接服务器...");
            socket = new Socket("localhost", 8088);
            System.out.println("服务器已连接成功！！！");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void Start() {
        try {
            //V4:启动用于接受服务端消息的线程
            ServerHandler handler = new ServerHandler();
            Thread t = new Thread(handler);
            t.start();


            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out, StandardCharsets.UTF_8);
            BufferedWriter bw = new BufferedWriter(osw);
            PrintWriter pw = new PrintWriter(bw, true);


            Scanner scanner = new Scanner(System.in);
            while (true) {
                String message = scanner.nextLine();
                if ("exit".equals(message)) {
                    break;
                }
                pw.println(message);


            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Clier4 clier = new Clier4();
        clier.Start();
    }

    //V4:该线程任务是负责不断接收来自服务端发送过来的消息并输出到控制台
    private class ServerHandler implements Runnable {
        public void run() {

            try {
                InputStream in = socket.getInputStream();
                InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
                BufferedReader br = new BufferedReader(isr);

                String message;
                while ((message = br.readLine()) != null) {
                    System.out.println(message);

                }
            } catch (IOException e) {
                e.printStackTrace();
            }


        }
    }
}
